{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"https://colab.research.google.com/github/oughtinc/ergo/blob/master/notebooks/covid-19-active.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Project: Estimating current Covid-19 infections (including undiagnosed) from multiple sources\n",
    "\n",
    "# Background\n",
    "\n",
    "This notebook allows forecasting different COVID-19 related parameters, by using probability distributions, and integrating spreadsheets and the forecasting platform Foretold.io.\n",
    "\n",
    "## Using the Colab\n",
    "- Run the colab by going to Runtime > \"Run All\"\n",
    "- You'll need to follow the instructions in the output of the \"Authentication\" section to allow the colab to read google sheets \n",
    "- If you want to use private foretold predictions, set foretold_token to the token of a bot account on foretold with access to the private channel\n",
    "- You can override parameters for individual regions with point estimates in the [Parameter Spreadsheet](https://docs.google.com/spreadsheets/d/1n42Op7sE3vUs4v2oSO19OM7yBH-9LIjPOp2dK_DtsMM/edit?usp=sharing)\n",
    "- The priority order for parameters is: 1. foretold distributions from the parameters table [https://www.foretold.io/c/1dd5b83a-075c-4c9f-b896-3172ec899f26/n/245566be-1e01-4dbf-9dcd-f0754b44e99e] 2. point estimates from the parameters google sheet 3. foretold distribution for the parameter for the world from the parameters table\n",
    "- The colab notebook will output active_infections_prediction.csv (active infections) and countermeasures.csv (countermeasures). If using Google Chrome they should download automatically, otherwise you can open the File pane on the left side of the screen and right click on the file to download\n",
    "- If you want to make changes, it's probably best to make your own copy of the colab\n",
    "\n",
    "## Notes\n",
    "- Currently, doesn't predict for regions with < 1000 cases or < 10 deaths. If you want to remove this restriction, comment out the cell after \"Restrict to countries with > 1000 cases and > 10 deaths\"\n",
    "\n",
    "- Does not yet directly support overriding parameters with a different foretold distribution\n",
    "- Does not yet directly support overriding history of the number of cases\n",
    "\n",
    "If you need to override any of these values for a specific region, you can likely load the data and modify the function that retrieves that parameter in the \"Data Retrieval Functions\" cell to substitute in your data\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Authentication"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install --progress-bar off --quiet typing_extensions\n",
    "!pip install --progress-bar off --quiet poetry  # Fixes https://github.com/python-poetry/poetry/issues/532\n",
    "!pip install --progress-bar off --quiet git+https://github.com/oughtinc/ergo.git@5614ff88bd13dbc7946be1e559e67ad633ffa76c\n",
    "!pip install --progress-bar off --quiet pendulum seaborn\n",
    "import ergo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import google\n",
    "#Authenticate (needs user interaction, so don't hide this cell)\n",
    "google.colab.auth.authenticate_user()\n",
    "\n",
    "foretold_token = \"YOUR-TOKEN\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## General"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install -q pendulum pycountry"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext google.colab.data_table"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import pendulum\n",
    "import gspread\n",
    "import numpy as np\n",
    "import math\n",
    "import pycountry\n",
    "import datetime\n",
    "import tqdm\n",
    "import time\n",
    "import seaborn\n",
    "import torch\n",
    "\n",
    "from matplotlib import pyplot as plt\n",
    "from io import StringIO\n",
    "from types import SimpleNamespace\n",
    "\n",
    "from oauth2client.client import GoogleCredentials"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ergo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Epimodel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!git clone -q https://github.com/epidemics/epimodel\n",
    "%cd /content/epimodel\n",
    "!git pull\n",
    "!git clone -q https://github.com/epidemics/epimodel-covid-data data\n",
    "%cd /content/epimodel/data\n",
    "!git pull\n",
    "%cd /content\n",
    "import sys\n",
    "sys.path.append('epimodel')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Epimodel needs unidecode:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install -q unidecode"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import epimodel\n",
    "regions = epimodel.RegionDataset.load('epimodel/data/regions.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def name_to_code(name):\n",
    "  try:\n",
    "      return regions.find_one_by_name(name).Code\n",
    "  except KeyError:\n",
    "      return \"\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Loading Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Utility Functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from uuid import UUID\n",
    "def is_uuid(s):\n",
    "  try:\n",
    "    uuid_obj = UUID(s, version=4)\n",
    "    return True\n",
    "  except ValueError:\n",
    "    return False\n",
    "\n",
    "def load_spreadsheet(url, sheet):\n",
    "    gc = gspread.authorize(GoogleCredentials.get_application_default())\n",
    "    wb = gc.open_by_url(url)\n",
    "    sheet = wb.worksheet(sheet)\n",
    "    values = sheet.get_all_values()\n",
    "    return values"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Estimating active infections\n",
    "\n",
    "In order to get an estimate of active infections, four different models are ensembled.\n",
    "\n",
    "The first three models are statistical and source their parameters from [this Foretold community](https://www.foretold.io/c/1dd5b83a-075c-4c9f-b896-3172ec899f26/notebooks), if available, and otherwise as point estimates from [this spreadsheet](https://docs.google.com/spreadsheets/d/1n42Op7sE3vUs4v2oSO19OM7yBH-9LIjPOp2dK_DtsMM/edit?usp=sharing). \n",
    "\n",
    "The fourth model is simply a human-estimated distribution of active infections.\n",
    "\n",
    "The models are described in more detail [here](https://www.notion.so/Ensemble-model-for-estimating-active-infections-00b72ecf6f674602ad27efb15249dd7e)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load Parameters from [Parameter Spreadsheet](https://docs.google.com/spreadsheets/d/1n42Op7sE3vUs4v2oSO19OM7yBH-9LIjPOp2dK_DtsMM/edit?usp=sharing)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_code(row):\n",
    "  if row[\"Province/State\"]:\n",
    "    return name_to_code(row[\"Province/State\"])\n",
    "  return name_to_code(row[\"Country/Region\"])\n",
    "\n",
    "def load_parameters(parameters_url, parameters_sheet):\n",
    "    values = load_spreadsheet(parameters_url, parameters_sheet)\n",
    "    d = {}\n",
    "    columns = values[0]\n",
    "    for row in values[1:]:\n",
    "      if row[0]:\n",
    "        code = name_to_code(row[0])\n",
    "      else:\n",
    "        code = name_to_code(row[1])\n",
    "      d[code] = {column: value for column, value in zip(columns, row)}\n",
    "    return d\n",
    "\n",
    "parameters = load_parameters('https://docs.google.com/spreadsheets/d/1n42Op7sE3vUs4v2oSO19OM7yBH-9LIjPOp2dK_DtsMM/edit', 'Parameters')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load Foretold Parameters"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Foretold Parameter JSON"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Need to replace with full json created by Ozzie\n",
    "foretold_lookup = [\n",
    "    {\n",
    "        \"name\": \"@locations/n-hungary\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Hungary\",\n",
    "            \"isoCode\": \"HU\",\n",
    "            \"foretoldName\": \"@locations/n-hungary\"\n",
    "        },\n",
    "        \"april19\": \"fceee746-01f9-42b5-9bb4-f5141196c163\",\n",
    "        \"april26\": \"126f6846-90b4-4e44-bc71-cf4918367344\",\n",
    "        \"may3\": \"1fdc46e2-c641-45f7-99cf-58469f2d5606\",\n",
    "        \"may17\": \"033e3efd-17d7-498a-bc63-28de2cdf225b\",\n",
    "        \"deathsAttributed\": \"2dee3f58-c6cd-4503-85f6-3e886f72fb50\",\n",
    "        \"infectionsAttributed\": \"0d4f247b-2d25-4289-a3ff-411e44067abf\",\n",
    "        \"timeToDeath\": \"9109a7d8-9eab-4094-93ea-15c92348033e\",\n",
    "        \"infectionFatalityRatio\": \"0d7bea59-100a-4945-9fcd-f5351e89950b\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-czech-republic\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Czech Republic\",\n",
    "            \"isoCode\": \"CZ\",\n",
    "            \"foretoldName\": \"@locations/n-czech-republic\"\n",
    "        },\n",
    "        \"april19\": \"c08c0ea4-09fe-45fe-9caf-9697a67f3262\",\n",
    "        \"april26\": \"46fbf258-70a9-4c39-9f3b-5d6f91930632\",\n",
    "        \"may3\": \"d892166d-d14c-4edf-8475-4b1b274c3656\",\n",
    "        \"may17\": \"fcab14bf-50e0-4c61-a9fa-cdf1835af007\",\n",
    "        \"deathsAttributed\": \"901e86f9-4841-4f9f-b555-d61417d1fb7a\",\n",
    "        \"infectionsAttributed\": \"2493fa7f-75f3-4396-bef5-5ae6b4bae324\",\n",
    "        \"timeToDeath\": \"7a0b3b4b-2a5c-4a0f-b500-c950d65fc028\",\n",
    "        \"infectionFatalityRatio\": \"d465c517-dce7-4d92-b173-26e022e74610\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-ukraine\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Ukraine\",\n",
    "            \"isoCode\": \"UA\",\n",
    "            \"foretoldName\": \"@locations/n-ukraine\"\n",
    "        },\n",
    "        \"april19\": \"a176eb57-39d6-4a9c-97be-58ab9eb9f55a\",\n",
    "        \"april26\": \"94750cd8-dcaf-4fad-a483-e46cfbba12e3\",\n",
    "        \"may3\": \"465af1bd-90f0-4c0e-bb2a-eec1047aa247\",\n",
    "        \"may17\": \"bcba6198-093c-4534-b17a-5815386ac64f\",\n",
    "        \"deathsAttributed\": \"d32ad94f-e8c4-4337-9a25-31e91bcfa63d\",\n",
    "        \"infectionsAttributed\": \"3b21bbf2-0287-4624-b409-4832f8055b0d\",\n",
    "        \"timeToDeath\": \"678bbd80-2864-4cd0-a63d-3ad027600e8b\",\n",
    "        \"infectionFatalityRatio\": \"34950965-c488-4b11-8956-c10a20e3d0e6\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-netherlands\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Netherlands\",\n",
    "            \"isoCode\": \"NL\",\n",
    "            \"foretoldName\": \"@locations/n-netherlands\"\n",
    "        },\n",
    "        \"april19\": \"562c5477-5037-45e1-b626-2b0dc33d92f9\",\n",
    "        \"april26\": \"b334bfcf-a3ef-49fa-9c4c-26aacd8ff337\",\n",
    "        \"may3\": \"c2f72783-a3fc-43d8-b92d-0d2abf52217c\",\n",
    "        \"may17\": \"87ae4c8d-5fdf-4961-9087-8639afa12124\",\n",
    "        \"deathsAttributed\": \"486f78ed-4c13-4adb-b399-95f9556c5fe3\",\n",
    "        \"infectionsAttributed\": \"0902bcff-0253-4eec-9864-d5643057fbae\",\n",
    "        \"timeToDeath\": \"7e4e9c8e-307f-4216-8463-9bb5f3fd08a4\",\n",
    "        \"infectionFatalityRatio\": \"06e42fc2-eb27-4897-818d-5e954964399c\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-united-kingdon\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"United Kingdon\",\n",
    "            \"isoCode\": \"GB\",\n",
    "            \"foretoldName\": \"@locations/n-united-kingdon\"\n",
    "        },\n",
    "        \"april19\": \"42476b18-e386-4c35-9f4b-a8f1cda264a9\",\n",
    "        \"april26\": \"7615f40d-f086-49b9-b5b5-f33d0e13a705\",\n",
    "        \"may3\": \"2a4336ac-a340-477a-9611-9d8578389304\",\n",
    "        \"may17\": \"d1778b1b-d956-414d-8aeb-82d6c3c08110\",\n",
    "        \"deathsAttributed\": \"315d095d-ae05-4e9d-80e3-1fb27246f7c2\",\n",
    "        \"infectionsAttributed\": \"76261599-422b-463c-ad4d-92962bc6c368\",\n",
    "        \"timeToDeath\": \"b88df3fd-8af7-46bf-8144-252703281580\",\n",
    "        \"infectionFatalityRatio\": \"70ed6dfb-0e84-462e-a06b-a985800be2d3\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-russia\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Russia\",\n",
    "            \"isoCode\": \"RU\",\n",
    "            \"foretoldName\": \"@locations/n-russia\"\n",
    "        },\n",
    "        \"april19\": \"9cf07291-7d43-4899-b391-bbf6977b5fee\",\n",
    "        \"april26\": \"7442037d-e749-4a1b-97a9-716f12363c70\",\n",
    "        \"may3\": \"3e919b5d-a049-4090-99b8-0f411f7366d5\",\n",
    "        \"may17\": \"a436113f-aa22-449b-951e-9f577d26fbb9\",\n",
    "        \"deathsAttributed\": \"57bf9b8b-40ea-43d2-9085-70d12500197d\",\n",
    "        \"infectionsAttributed\": \"cdc51237-62ca-4157-9d3f-f1c963add9aa\",\n",
    "        \"timeToDeath\": \"a4f58a70-ef24-493a-a835-a1051f23f3fd\",\n",
    "        \"infectionFatalityRatio\": \"0f5e66eb-e615-4fcc-a0b9-f9182bb2c03b\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-france\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"France\",\n",
    "            \"isoCode\": \"FR\",\n",
    "            \"foretoldName\": \"@locations/n-france\"\n",
    "        },\n",
    "        \"april19\": \"70407aee-ffcf-4466-b352-6b05dc424c10\",\n",
    "        \"april26\": \"bd443efd-12f5-4db4-83d4-d65567797c91\",\n",
    "        \"may3\": \"4bb96a2d-6103-40af-be6f-2e33f48a4298\",\n",
    "        \"may17\": \"44cce87c-649a-4414-ab97-ff24a5fb5167\",\n",
    "        \"deathsAttributed\": \"bb4c4a26-4882-4a12-a449-6df4fc1d4b75\",\n",
    "        \"infectionsAttributed\": \"855bece8-0364-487d-adf2-0e253fb30475\",\n",
    "        \"timeToDeath\": \"dc649a48-f8b1-47cd-ba36-6190e8934108\",\n",
    "        \"infectionFatalityRatio\": \"5f8c61ac-00b4-4438-bc12-a4c4444a9676\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-belarus\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Belarus\",\n",
    "            \"isoCode\": \"BY\",\n",
    "            \"foretoldName\": \"@locations/n-belarus\"\n",
    "        },\n",
    "        \"april19\": \"98889cef-85b2-4672-80d4-c6eee321e0c4\",\n",
    "        \"april26\": \"e778ebe3-b7c4-4b2b-b210-2015967ef772\",\n",
    "        \"may3\": \"b568f648-4542-4487-a540-f91cb571fa22\",\n",
    "        \"may17\": \"eaa948ec-be88-4efd-a04f-c5cba0894a0a\",\n",
    "        \"deathsAttributed\": \"60c88d73-d8fd-42ca-8259-cafa032fb21d\",\n",
    "        \"infectionsAttributed\": \"a294bf30-f589-4b2a-a28b-c50942c26163\",\n",
    "        \"timeToDeath\": \"1d90b66b-2c43-42a3-8e2d-b221973a90c8\",\n",
    "        \"infectionFatalityRatio\": \"1f9e4a9f-5099-4f74-984e-6f184b0467e5\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-spain\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Spain\",\n",
    "            \"isoCode\": \"ES\",\n",
    "            \"foretoldName\": \"@locations/n-spain\"\n",
    "        },\n",
    "        \"april19\": \"1e17b500-92fe-4ef5-a36c-77182fc5f712\",\n",
    "        \"april26\": \"5477c30e-8303-4c5c-93f0-27317226e56f\",\n",
    "        \"may3\": \"70a5c96f-1571-4b83-90a3-cc775dd72f6f\",\n",
    "        \"may17\": \"0dd70995-b4f0-472a-9095-fbc71d5255ff\",\n",
    "        \"deathsAttributed\": \"eff08726-220c-4da5-94fc-a3ba26c44421\",\n",
    "        \"infectionsAttributed\": \"230ba580-9681-4379-9fe5-3639d73adcce\",\n",
    "        \"timeToDeath\": \"8deae807-bdd3-43c0-a8a4-6eb98c358e83\",\n",
    "        \"infectionFatalityRatio\": \"3103be98-d7d5-4335-b279-fde5fe5f670b\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-italy\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Italy\",\n",
    "            \"isoCode\": \"IT\",\n",
    "            \"foretoldName\": \"@locations/n-italy\"\n",
    "        },\n",
    "        \"april19\": \"b6e8caf6-afec-428a-adf3-44b962d99383\",\n",
    "        \"april26\": \"7422ee75-a130-4b24-b025-d349df24100e\",\n",
    "        \"may3\": \"90e76d42-2685-47ff-b8fe-fb80be829333\",\n",
    "        \"may17\": \"a1770f21-55a6-415b-8da2-f71411d1f0ae\",\n",
    "        \"deathsAttributed\": \"150b74e0-a92b-41d8-8020-0078bdb5c836\",\n",
    "        \"infectionsAttributed\": \"4a3dec41-0688-4605-85ac-cae427e9ca51\",\n",
    "        \"timeToDeath\": \"af23f463-4231-493a-897e-9d8b903cac90\",\n",
    "        \"infectionFatalityRatio\": \"f2456630-cef3-42dd-8fef-d6e6a95e5d2c\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-nepal\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Nepal\",\n",
    "            \"foretoldName\": \"@locations/n-nepal\"\n",
    "        },\n",
    "        \"april19\": \"c049c851-a806-4eb7-be7c-fbe988e88121\",\n",
    "        \"april26\": \"a9447b87-fd25-49b5-81f1-f89880bc196d\",\n",
    "        \"may3\": \"3845ef90-ccb1-418f-a6f3-ee5131fdf167\",\n",
    "        \"may17\": \"0b9c19cb-945d-4523-95b1-97d5b578318b\",\n",
    "        \"deathsAttributed\": \"a9335e1d-2e85-4bfd-b8b0-4d6915604997\",\n",
    "        \"infectionsAttributed\": \"c11e38a3-02ef-4998-99ff-500621f60e5c\",\n",
    "        \"timeToDeath\": \"b5eb2dc1-e1d3-4e92-97c5-79d45299f827\",\n",
    "        \"infectionFatalityRatio\": \"908ceff9-c8d7-4a07-8984-1f43bde37459\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-india\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"India\",\n",
    "            \"isoCode\": \"IN\",\n",
    "            \"foretoldName\": \"@locations/n-india\"\n",
    "        },\n",
    "        \"april19\": \"d5115540-209e-4e3f-9a38-76e45b60574a\",\n",
    "        \"april26\": \"c5b8f0f2-b4fa-4bf3-a375-6d0e8cd0bbb0\",\n",
    "        \"may3\": \"a3808a82-6424-40c7-bf2e-7459540656b9\",\n",
    "        \"may17\": \"a011d2a3-3bc2-4045-9b43-a4381325d5f7\",\n",
    "        \"deathsAttributed\": \"0b47a481-72d5-486f-84cb-a2f3ab20c6d0\",\n",
    "        \"infectionsAttributed\": \"deecf45a-03c5-457e-ba8e-ed51b63eab01\",\n",
    "        \"timeToDeath\": \"c1bfe7db-0bfc-4265-ab5e-388ddf349336\",\n",
    "        \"infectionFatalityRatio\": \"ad839ed9-d045-417b-8866-290bec82bdd2\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-myanmar\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Myanmar\",\n",
    "            \"isoCode\": \"MM\",\n",
    "            \"foretoldName\": \"@locations/n-myanmar\"\n",
    "        },\n",
    "        \"april19\": \"cd3e2711-1e35-42bc-88a2-39e23b1dc628\",\n",
    "        \"april26\": \"4d5f8a9f-7dd6-419e-aebe-3909ae6121f7\",\n",
    "        \"may3\": \"9005b8b6-49db-4368-a670-92f50ce434cf\",\n",
    "        \"may17\": \"b7eacba3-5801-4989-93aa-46fdba2c3293\",\n",
    "        \"deathsAttributed\": \"3860aaa1-146f-46f3-8fe3-c75e5cac8f6d\",\n",
    "        \"infectionsAttributed\": \"ba82bd02-f0e7-42e3-9383-f84dfe6027c7\",\n",
    "        \"timeToDeath\": \"73531577-c6de-41cc-8f8e-9d26c0b0aa44\",\n",
    "        \"infectionFatalityRatio\": \"63659069-747a-4990-b5f0-9b8bc95aaafa\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-azerbaijan\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Azerbaijan\",\n",
    "            \"isoCode\": \"AZ\",\n",
    "            \"foretoldName\": \"@locations/n-azerbaijan\"\n",
    "        },\n",
    "        \"april19\": \"35244016-cabe-4578-a671-bc4f00f709e7\",\n",
    "        \"april26\": \"1e5e52c1-8d4b-4fac-b439-7edd1284fd28\",\n",
    "        \"may3\": \"8c037be2-960d-4374-9e96-730d279eac07\",\n",
    "        \"may17\": \"4c01b1d0-7617-4246-917b-43c7e3a2d47d\",\n",
    "        \"deathsAttributed\": \"d62098b8-3b9a-4413-b2b4-2f883f7d3ead\",\n",
    "        \"infectionsAttributed\": \"0eae20cb-6ac7-494c-bef7-558cff55ba67\",\n",
    "        \"timeToDeath\": \"a84dae59-2c14-4c5d-bd87-29fda38edb7b\",\n",
    "        \"infectionFatalityRatio\": \"aec8bcce-d1b4-44bf-9dac-8293d1acb740\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-kazakhstan\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Kazakhstan\",\n",
    "            \"isoCode\": \"KZ\",\n",
    "            \"foretoldName\": \"@locations/n-kazakhstan\"\n",
    "        },\n",
    "        \"april19\": \"2699f03e-3c2c-4c46-8af0-07c18d82c479\",\n",
    "        \"april26\": \"97784799-3d90-4ca7-8cad-0fec3b7d9e9d\",\n",
    "        \"may3\": \"798b665a-afeb-4b42-9d5a-dd6819f87388\",\n",
    "        \"may17\": \"6b375aff-6ef9-48db-bc98-cc1a99fe28b7\",\n",
    "        \"deathsAttributed\": \"874e1d19-f952-41a5-9446-ab7dd562dc30\",\n",
    "        \"infectionsAttributed\": \"9c0aafe1-86d4-43c5-a987-0a74769778ac\",\n",
    "        \"timeToDeath\": \"8bd6d6a8-f689-4e67-90d3-60e09e9de3ad\",\n",
    "        \"infectionFatalityRatio\": \"7e0f9430-1b0b-41e1-9102-5bd481436550\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-uzbekistan\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Uzbekistan\",\n",
    "            \"isoCode\": \"UZ\",\n",
    "            \"foretoldName\": \"@locations/n-uzbekistan\"\n",
    "        },\n",
    "        \"april19\": \"2d483a20-b992-4c4b-9c22-3f69764580f7\",\n",
    "        \"april26\": \"bc401ff6-f32a-41dd-a4d0-4bbcad3785b6\",\n",
    "        \"may3\": \"29bd5c23-1b07-4b98-bb6f-8835ee68e0e5\",\n",
    "        \"may17\": \"a1b9b08b-0e67-446c-b9c9-7836752c4c83\",\n",
    "        \"deathsAttributed\": \"8014e845-1977-4da6-af79-ed43ac402674\",\n",
    "        \"infectionsAttributed\": \"e1db4a03-85c1-4256-bf7a-63dea8001248\",\n",
    "        \"timeToDeath\": \"c15df4ff-6a75-4206-8f17-2c1c3a81dd8a\",\n",
    "        \"infectionFatalityRatio\": \"91de9fbf-8ac0-4cf7-b123-1db4b634e71f\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-saudi-arabia\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Saudi Arabia\",\n",
    "            \"isoCode\": \"SA\",\n",
    "            \"foretoldName\": \"@locations/n-saudi-arabia\"\n",
    "        },\n",
    "        \"april19\": \"d8255ff3-a729-4e27-bb8f-c41eba8293ac\",\n",
    "        \"april26\": \"4aaa2b3d-bed7-4915-9b14-9db3e99e85b5\",\n",
    "        \"may3\": \"e5e9ce79-cb2b-4683-8bc2-da1125176303\",\n",
    "        \"may17\": \"d6b36a43-07cd-4406-8fee-a0043d11a23b\",\n",
    "        \"deathsAttributed\": \"823bd318-bea9-436d-afdb-bdeef07af01c\",\n",
    "        \"infectionsAttributed\": \"c729ad9d-12cb-4d09-9989-a500c382085e\",\n",
    "        \"timeToDeath\": \"8ac56ba8-598a-4780-9f80-be32d438467d\",\n",
    "        \"infectionFatalityRatio\": \"9480970b-ea5d-4528-8dd8-50290125432c\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-maldives\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Maldives\",\n",
    "            \"isoCode\": \"MV\",\n",
    "            \"foretoldName\": \"@locations/n-maldives\"\n",
    "        },\n",
    "        \"april19\": \"9b40c1b5-614b-4bd5-bf1a-5d517cefe9bc\",\n",
    "        \"april26\": \"9a8b8053-38c9-42c0-8572-ae9515ed3f78\",\n",
    "        \"may3\": \"ba603b63-d0b5-464b-8a2a-c7c50ac5fa9e\",\n",
    "        \"may17\": \"af970a0f-79b2-4f79-bd78-2a5b4e5586d0\",\n",
    "        \"deathsAttributed\": \"1666a2ac-22c1-4f30-9154-ec1314e726fa\",\n",
    "        \"infectionsAttributed\": \"d7c78665-a563-4467-be49-ec9e80538ce3\",\n",
    "        \"timeToDeath\": \"3be92417-597a-495b-b883-def91c7f82dd\",\n",
    "        \"infectionFatalityRatio\": \"5de1f32e-f3a8-4085-9c94-0b7b2b4d2c8b\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-iran\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Iran\",\n",
    "            \"isoCode\": \"IR\",\n",
    "            \"foretoldName\": \"@locations/n-iran\"\n",
    "        },\n",
    "        \"april19\": \"99d1aa7c-cd70-41c9-a998-fc3dc57b2d79\",\n",
    "        \"april26\": \"b41007b0-2256-4f06-b671-f6de0cca61e6\",\n",
    "        \"may3\": \"d4f2fa4d-3aa4-4f85-b6c6-78ac15cdc2ff\",\n",
    "        \"may17\": \"de892638-2d8d-4364-b6a7-3ca9ce7eb899\",\n",
    "        \"deathsAttributed\": \"5957205a-c3d9-4d24-a8ec-bbdd25a8a86b\",\n",
    "        \"infectionsAttributed\": \"d9f7b01c-c70d-4035-bb88-88bc1ba7626c\",\n",
    "        \"timeToDeath\": \"459ccf8b-1fa9-4b63-aaa2-78a98ba4051b\",\n",
    "        \"infectionFatalityRatio\": \"9454b639-0bb4-4e90-b784-3cf2388348a0\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-pakistan\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Pakistan\",\n",
    "            \"isoCode\": \"PK\",\n",
    "            \"foretoldName\": \"@locations/n-pakistan\"\n",
    "        },\n",
    "        \"april19\": \"61743ebe-5a7f-4375-bd4a-0ab8ea4fc2c6\",\n",
    "        \"april26\": \"77b73b79-3fe8-412a-802a-298697ce6e66\",\n",
    "        \"may3\": \"ba756e89-4cfa-4188-bc6a-f22a943d5cc4\",\n",
    "        \"may17\": \"f578bf44-0d11-474a-83db-145082e3de35\",\n",
    "        \"deathsAttributed\": \"7ad878e6-5175-44a2-86ee-777c27c55877\",\n",
    "        \"infectionsAttributed\": \"762222b6-aedc-4b61-82ba-5340fd984d92\",\n",
    "        \"timeToDeath\": \"5e4830c0-69e7-44de-91b1-51c2a5f0a4a0\",\n",
    "        \"infectionFatalityRatio\": \"682befc6-3c19-48b0-98a0-bf52c5221c06\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-pakistan-balochistan\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Balochistan (Pakistan)\",\n",
    "            \"foretoldName\": \"@locations/n-pakistan-balochistan\"\n",
    "        },\n",
    "        \"april19\": \"8683b39d-2e9b-4994-891d-cdec9d9e0fa1\",\n",
    "        \"april26\": \"1b21f58e-5de9-42e0-b107-a4ae8b271c92\",\n",
    "        \"may3\": \"d81b580a-08c7-4377-8485-1ac355abf58a\",\n",
    "        \"may17\": \"be924708-f253-4d64-91f9-6835473d9db3\",\n",
    "        \"deathsAttributed\": \"4a5246fd-20af-47b6-9c60-86954aea21b6\",\n",
    "        \"infectionsAttributed\": \"a75bb2fc-9333-4b35-b012-4a0c332aa02c\",\n",
    "        \"timeToDeath\": \"2c1e7918-a2ec-459f-88be-5ccaa076f7e3\",\n",
    "        \"infectionFatalityRatio\": \"28925e55-336a-4556-b642-3ae6ee5ee1b3\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-mumbai\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Mumbai (India)\",\n",
    "            \"foretoldName\": \"@locations/n-mumbai\"\n",
    "        },\n",
    "        \"april19\": \"e5567c34-8384-4670-9497-f987b65ef693\",\n",
    "        \"april26\": \"985f7858-4886-497f-9fb1-f82b051239b7\",\n",
    "        \"may3\": \"247de3c8-38d5-459d-be3a-73c2d2c258f6\",\n",
    "        \"may17\": \"0a9b2314-c44a-4b74-8999-83f8df5ce322\",\n",
    "        \"deathsAttributed\": \"d070f4ac-6834-4d65-a8b8-af0b10ebefc5\",\n",
    "        \"infectionsAttributed\": \"56eb2739-4c26-4700-a9ed-330d56e9d054\",\n",
    "        \"timeToDeath\": \"cd1f9036-3360-4838-bead-a2d72022451d\",\n",
    "        \"infectionFatalityRatio\": \"51f88e70-b1b2-430c-aff7-47cf5ba70987\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-bangularu\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Bangaluru (India)\",\n",
    "            \"foretoldName\": \"@locations/n-bangularu\"\n",
    "        },\n",
    "        \"april19\": \"d346fd04-9f23-4261-a47e-e8c088500a7b\",\n",
    "        \"april26\": \"056db717-02fd-4c42-91da-447469d50a61\",\n",
    "        \"may3\": \"dc049c11-d016-4ce4-93d5-700f4bc70937\",\n",
    "        \"may17\": \"0bb99ce6-1e3c-4b8b-bcbd-890ca382676b\",\n",
    "        \"deathsAttributed\": \"9969f2b2-6471-4599-9a6e-63107bbe153b\",\n",
    "        \"infectionsAttributed\": \"bad11dd7-0af6-46c4-9282-a24500fc5687\",\n",
    "        \"timeToDeath\": \"3bbe376f-2710-4d7c-95a2-e514af70b96f\",\n",
    "        \"infectionFatalityRatio\": \"121bd923-d349-4c99-8d82-8027d49bd969\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-chennai\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Chennai (India)\",\n",
    "            \"foretoldName\": \"@locations/n-chennai\"\n",
    "        },\n",
    "        \"april19\": \"84200f66-f029-49a5-bebe-1d197f7543d8\",\n",
    "        \"april26\": \"5ea46403-0f15-466e-b6fe-3e69b4fabb1a\",\n",
    "        \"may3\": \"31ff9cfd-5f87-4981-ae48-169b83cbb099\",\n",
    "        \"may17\": \"17fba54d-fb08-4fd0-bdd6-5219555f329c\",\n",
    "        \"deathsAttributed\": \"3251bf68-cc41-4a1f-8a82-ef63fefe2165\",\n",
    "        \"infectionsAttributed\": \"34eaaf36-1749-4339-9434-64b1036ac9f8\",\n",
    "        \"timeToDeath\": \"2d983268-6a7a-44a0-a7a4-071df77a2201\",\n",
    "        \"infectionFatalityRatio\": \"412482d9-8317-496e-8236-7288486b5e82\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-nigeria\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Nigeria\",\n",
    "            \"isoCode\": \"NG\",\n",
    "            \"foretoldName\": \"@locations/n-nigeria\"\n",
    "        },\n",
    "        \"april19\": \"8ba68b08-8d4b-4427-ab37-c6753b49b4e6\",\n",
    "        \"april26\": \"753cf457-693d-4c4a-81d9-f4afea52007e\",\n",
    "        \"may3\": \"670aae22-358c-4a93-8fde-78478360bb32\",\n",
    "        \"may17\": \"9f49e806-1be7-472f-bb68-256d7716dbad\",\n",
    "        \"deathsAttributed\": \"0babfbc1-2443-471d-a91e-ee56d380e25a\",\n",
    "        \"infectionsAttributed\": \"b2bea67c-0c4f-4330-837c-0aea84970d75\",\n",
    "        \"timeToDeath\": \"336d982d-9d18-49c7-8f5f-49b14263db32\",\n",
    "        \"infectionFatalityRatio\": \"17288b4b-e416-4c37-8018-e5d623343484\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-ethiopia\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Ethiopia\",\n",
    "            \"isoCode\": \"ET\",\n",
    "            \"foretoldName\": \"@locations/n-ethiopia\"\n",
    "        },\n",
    "        \"april19\": \"a3df96e4-b5cd-4aff-bb01-968729d528c6\",\n",
    "        \"april26\": \"a26733b9-7404-46a6-ab74-9b84f79305f0\",\n",
    "        \"may3\": \"b89d66f4-80db-4bc2-ba45-5961a3d1db07\",\n",
    "        \"may17\": \"fd379538-915c-4e06-9256-b5086d862c35\",\n",
    "        \"deathsAttributed\": \"2edcdc5b-d8b3-4204-bf9d-67dc34a5b4c6\",\n",
    "        \"infectionsAttributed\": \"7313162c-e096-479a-a1e8-9467db9c1663\",\n",
    "        \"timeToDeath\": \"102796b0-5466-4d1c-b497-0928b6326443\",\n",
    "        \"infectionFatalityRatio\": \"5002ea92-08c3-4359-8871-8735d6898cc5\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-central-african-republic\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Central African Republic\",\n",
    "            \"isoCode\": \"CF\",\n",
    "            \"foretoldName\": \"@locations/n-central-african-republic\"\n",
    "        },\n",
    "        \"april19\": \"45932c74-7f88-449c-bcca-ef15e2fe4156\",\n",
    "        \"april26\": \"1361ea67-22ee-491e-8fd1-8c771740ba63\",\n",
    "        \"may3\": \"38395987-83ac-4758-9404-15e128b80cc9\",\n",
    "        \"may17\": \"ab0332dc-6624-4548-b6ed-7d8002efafa8\",\n",
    "        \"deathsAttributed\": \"8d40e5f0-d2be-4143-a0ca-d3239ff64e1c\",\n",
    "        \"infectionsAttributed\": \"230e3edd-fb04-4b60-b67f-ca56e6d53ec0\",\n",
    "        \"timeToDeath\": \"2187857a-02a4-4992-bbb6-e8b60bcdaaf9\",\n",
    "        \"infectionFatalityRatio\": \"bd1a383e-aeae-4aa8-a50b-9cce1eec26d4\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-south-africa\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"South Africa\",\n",
    "            \"isoCode\": \"ZA\",\n",
    "            \"foretoldName\": \"@locations/n-south-africa\"\n",
    "        },\n",
    "        \"april19\": \"06b3f1e7-75ac-4521-9869-daf23d78b9cb\",\n",
    "        \"april26\": \"326e6249-c8f0-42ba-9344-0b523dd55369\",\n",
    "        \"may3\": \"8e23b00d-13c8-477f-9fec-60a9709fa8c8\",\n",
    "        \"may17\": \"c335eb3e-ce57-41bb-b42b-a6ff47d59f5f\",\n",
    "        \"deathsAttributed\": \"141b8696-1e10-4ff2-b4af-67c78ba03216\",\n",
    "        \"infectionsAttributed\": \"abe98728-bf21-4a2f-a95b-28f6ccd58926\",\n",
    "        \"timeToDeath\": \"c5ec06c9-593a-4fe1-9dab-d292e31d3c38\",\n",
    "        \"infectionFatalityRatio\": \"eee32571-b22b-46af-bb1f-1f6b468b9e10\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-ghana\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Ghana\",\n",
    "            \"isoCode\": \"GH\",\n",
    "            \"foretoldName\": \"@locations/n-ghana\"\n",
    "        },\n",
    "        \"april19\": \"2363e08b-a632-457b-a190-f0a8f3e7c3a2\",\n",
    "        \"april26\": \"00a47809-a88a-47d4-86e5-99096fc98030\",\n",
    "        \"may3\": \"323f0a91-de83-4353-92ae-00471eb096d1\",\n",
    "        \"may17\": \"c4537d29-212e-464f-8341-094a9c32d425\",\n",
    "        \"deathsAttributed\": \"f699c231-c333-44dc-b7f8-1b04c5a11454\",\n",
    "        \"infectionsAttributed\": \"f40c7f8f-ed00-4bb0-99bf-e2e43b46ed72\",\n",
    "        \"timeToDeath\": \"3af6bbe7-ff5a-4bcb-bc77-5f43104d7883\",\n",
    "        \"infectionFatalityRatio\": \"994f13ba-a70e-4364-92ee-ca60289215e1\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-botswana\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Botswana\",\n",
    "            \"isoCode\": \"BW\",\n",
    "            \"foretoldName\": \"@locations/n-botswana\"\n",
    "        },\n",
    "        \"april19\": \"6f19c848-98d0-4795-8e56-d704968ac782\",\n",
    "        \"april26\": \"68b939f6-0615-4b83-8612-1803f41053c3\",\n",
    "        \"may3\": \"e5d74463-b35b-4973-a3d4-efd4a34c148c\",\n",
    "        \"may17\": \"edf8458a-9d6d-4482-b791-e8919267006c\",\n",
    "        \"deathsAttributed\": \"02031e71-71a9-4ddd-af77-9564617e6885\",\n",
    "        \"infectionsAttributed\": \"4d8f6285-d776-456a-a9fa-651c9b1737d1\",\n",
    "        \"timeToDeath\": \"9bda5fd9-8a24-4a30-a44d-16cd112f620c\",\n",
    "        \"infectionFatalityRatio\": \"ad9a6300-72fd-456c-966f-c815ec3bdb39\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-egypt\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Egypt\",\n",
    "            \"isoCode\": \"EG\",\n",
    "            \"foretoldName\": \"@locations/n-egypt\"\n",
    "        },\n",
    "        \"april19\": \"0d16ad1e-1471-4f79-81b5-744801421678\",\n",
    "        \"april26\": \"f5cd38e9-86e6-4bd3-9d5f-1c3ffc48bf91\",\n",
    "        \"may3\": \"e49c026f-5c4b-433c-ad7b-1d8a73123b99\",\n",
    "        \"may17\": \"9342ddd7-b003-496c-b0a6-cea0a14d1ed2\",\n",
    "        \"deathsAttributed\": \"03997a16-1bc9-474a-81f6-de48961c706c\",\n",
    "        \"infectionsAttributed\": \"03c6ade8-cf39-4225-b0e0-fb7cf62390df\",\n",
    "        \"timeToDeath\": \"ca33ba7f-6482-4e3a-8469-7a21c6ff13ad\",\n",
    "        \"infectionFatalityRatio\": \"9ed98b6d-ca46-41e6-8636-6678fd941b2d\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-africa\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Africa\",\n",
    "            \"isoCode\": \"W-AF\",\n",
    "            \"foretoldName\": \"@locations/n-africa\"\n",
    "        },\n",
    "        \"april19\": \"d58bb5e6-cb38-4f24-a82d-59831d7d3aab\",\n",
    "        \"april26\": \"39ecd14f-e434-4397-a2f8-84c34fd24149\",\n",
    "        \"may3\": \"e3443eb1-a15b-453a-b3e8-59e076937359\",\n",
    "        \"may17\": \"e1a5c8cb-9616-4a70-83a1-7b910c4c7c2c\",\n",
    "        \"deathsAttributed\": \"d10b810a-c8c9-4747-917d-fc483b69f11a\",\n",
    "        \"infectionsAttributed\": \"c9bf1f21-f6dd-41b3-a8a0-bc25c2f5f483\",\n",
    "        \"timeToDeath\": \"70e2665e-0290-43c6-814c-9e1e4f942b9b\",\n",
    "        \"infectionFatalityRatio\": \"d9a5f7a9-12d8-4a67-8ff2-6083daefb069\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-tanzania\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Tanzania\",\n",
    "            \"isoCode\": \"TZ\",\n",
    "            \"foretoldName\": \"@locations/n-tanzania\"\n",
    "        },\n",
    "        \"april19\": \"1f805578-533d-4cb9-8036-4dd832ca4144\",\n",
    "        \"april26\": \"c18a2ae0-e0fb-437d-a41c-6d2eda05679c\",\n",
    "        \"may3\": \"39145127-488d-4ef3-9771-aa45c3e907cd\",\n",
    "        \"may17\": \"de1bf5fe-d6fe-48b6-8649-491f7605eccd\",\n",
    "        \"deathsAttributed\": \"a508bd09-630d-49e1-a0ec-5c3e80df24ee\",\n",
    "        \"infectionsAttributed\": \"d603f1bf-701a-4166-a62e-1f0383ff8a7e\",\n",
    "        \"timeToDeath\": \"f7ed278a-f2ea-4452-b8cc-8831efc14933\",\n",
    "        \"infectionFatalityRatio\": \"34692218-a2f7-478c-9859-0467c50dabd8\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-dar-es-salaam\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Dar es Salaam (Tanzania)\",\n",
    "            \"foretoldName\": \"@locations/n-dar-es-salaam\"\n",
    "        },\n",
    "        \"april19\": \"f7f872e0-935a-4ce6-ba6c-31b8aff8ab61\",\n",
    "        \"april26\": \"ebe7d72a-148e-42c7-9014-3f7e3bbbb31f\",\n",
    "        \"may3\": \"339af780-79bb-4265-bfa0-339ef53938c3\",\n",
    "        \"may17\": \"2cd62057-5938-4b01-ae0a-4b674dbb44cb\",\n",
    "        \"deathsAttributed\": \"ad61b46c-7cf8-4ea5-b4a4-9e1cb24c0d40\",\n",
    "        \"infectionsAttributed\": \"76c68e6a-ffbf-42ec-89d5-f66bf4d88a41\",\n",
    "        \"timeToDeath\": \"2fb00922-2401-4ccb-8e51-90b612f6a954\",\n",
    "        \"infectionFatalityRatio\": \"ea12b45e-7622-4c35-8c2a-613f1383b7d5\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-bangui\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Bangui (Central African Republic)\",\n",
    "            \"foretoldName\": \"@locations/n-bangui\"\n",
    "        },\n",
    "        \"april19\": \"674fe066-7904-4979-83aa-52ad4ef26598\",\n",
    "        \"april26\": \"ef621706-aa58-45b7-9cac-3aa47100ebcd\",\n",
    "        \"may3\": \"cd842f3d-8147-491a-ab4a-5f74a6bf91fb\",\n",
    "        \"may17\": \"d46eb996-5629-4ef7-b255-d1f04d24a92b\",\n",
    "        \"deathsAttributed\": \"67117b33-8678-4cbe-9ec5-3e5eb88dba9b\",\n",
    "        \"infectionsAttributed\": \"28fda8e1-e198-4f87-998e-9f1a01a96541\",\n",
    "        \"timeToDeath\": \"36b53810-c094-4697-9d4a-0410f4c92d3b\",\n",
    "        \"infectionFatalityRatio\": \"35eac892-190f-4dcd-9fcc-2da1cf7fd21c\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-argentina\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Argentina\",\n",
    "            \"isoCode\": \"AR\",\n",
    "            \"foretoldName\": \"@locations/n-argentina\"\n",
    "        },\n",
    "        \"april19\": \"372f63db-8ac8-432c-951a-9ab03499942f\",\n",
    "        \"april26\": \"6bebe133-f437-45a8-b107-b6d5356a9e26\",\n",
    "        \"may3\": \"30e6abeb-46d7-49c9-bab3-b5aa259c3755\",\n",
    "        \"may17\": \"14732518-00f5-4a4e-a056-29cadd2143d6\",\n",
    "        \"deathsAttributed\": \"ea2c876a-6939-47f8-884d-eb6b737df0ff\",\n",
    "        \"infectionsAttributed\": \"8882e3f5-62a7-45fc-929c-1d529e2b4cf5\",\n",
    "        \"timeToDeath\": \"3374dfa2-1354-40a5-85fd-2763de9fd7af\",\n",
    "        \"infectionFatalityRatio\": \"d1f8a394-15d3-4dce-a19e-362e5b6e4dbe\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-canada\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Canada\",\n",
    "            \"isoCode\": \"CA\",\n",
    "            \"foretoldName\": \"@locations/n-canada\"\n",
    "        },\n",
    "        \"april19\": \"6be2450d-2f7a-4658-8d35-4a9d64096cf3\",\n",
    "        \"april26\": \"0abd65b7-0d76-4706-87c5-890b9887e9df\",\n",
    "        \"may3\": \"ccb7d692-6e35-48a6-b62a-dd263659779d\",\n",
    "        \"may17\": \"7cc94a5e-1a94-4c80-a08d-cc4aeb39e9bf\",\n",
    "        \"deathsAttributed\": \"bb17604e-7b49-4a4f-ba48-a203ad7bdf13\",\n",
    "        \"infectionsAttributed\": \"214e34c0-4d9d-4623-9c0c-8a74a5601ab6\",\n",
    "        \"timeToDeath\": \"b098b562-f43f-4f08-b5ed-51eb0fcfbdfb\",\n",
    "        \"infectionFatalityRatio\": \"5fe6afd4-4bb1-421e-b5fb-5b31e59fd8ec\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-brazil\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Brazil\",\n",
    "            \"isoCode\": \"BR\",\n",
    "            \"foretoldName\": \"@locations/n-brazil\"\n",
    "        },\n",
    "        \"april19\": \"75c2446f-1c46-4243-acf2-d22cafc68edb\",\n",
    "        \"april26\": \"0d1d9368-2e1d-4ce9-81fa-14cf397fe8a4\",\n",
    "        \"may3\": \"5aa4a5aa-bcbb-4eef-91a1-b15b9221e804\",\n",
    "        \"may17\": \"e9cbf9db-0474-440e-bdea-51c94fedbfc2\",\n",
    "        \"deathsAttributed\": \"a1eb540f-47cf-4fb5-98c9-9942753f938a\",\n",
    "        \"infectionsAttributed\": \"fb4d7053-8128-43c9-b0f0-4a9d3789d3cd\",\n",
    "        \"timeToDeath\": \"0401a033-ca6e-40e1-a3de-709f677fc980\",\n",
    "        \"infectionFatalityRatio\": \"b41b0c74-6db1-43cc-8430-1fd13c319263\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-dominica\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Dominica (Caribbean)\",\n",
    "            \"isoCode\": \"DM\",\n",
    "            \"foretoldName\": \"@locations/n-dominica\"\n",
    "        },\n",
    "        \"april19\": \"75b5b52b-75da-4162-bdd5-a50f4cb12e81\",\n",
    "        \"april26\": \"9e67b467-361d-4661-a2de-c59cc8e101a1\",\n",
    "        \"may3\": \"021ccbeb-1ed4-4f09-acc7-3c9fda9fc295\",\n",
    "        \"may17\": \"e3db1040-9662-4b44-af01-542c3b1db4dd\",\n",
    "        \"deathsAttributed\": \"9270f742-0977-42ea-9b7e-5f12b83bc21b\",\n",
    "        \"infectionsAttributed\": \"41f67dd5-b58b-44a6-a312-1936bdc30ed5\",\n",
    "        \"timeToDeath\": \"3c5ca22e-26d6-490f-8279-9bbf0d1876a6\",\n",
    "        \"infectionFatalityRatio\": \"d0cd2283-ac11-49d1-8cfb-ff5b470be9b7\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-united-states-of-america\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"United States of America\",\n",
    "            \"isoCode\": \"US \",\n",
    "            \"foretoldName\": \"@locations/n-united-states-of-america\"\n",
    "        },\n",
    "        \"april19\": \"06deab80-6610-4bff-a75d-30a6028790dd\",\n",
    "        \"april26\": \"38471260-a79a-4807-942d-0784aa19c2c2\",\n",
    "        \"may3\": \"92c2f2f3-91aa-48b8-aaa3-c9bb402c0b08\",\n",
    "        \"may17\": \"96040d3b-afcb-425a-a1ab-8fed5f5ea861\",\n",
    "        \"deathsAttributed\": \"288302d4-28d4-4678-aac7-43e9d41b3ec5\",\n",
    "        \"infectionsAttributed\": \"2a85dc03-5983-46e1-8178-46e9c1e4e812\",\n",
    "        \"timeToDeath\": \"6e812b42-4dd2-43f3-8f4c-a51ba5c53bae\",\n",
    "        \"infectionFatalityRatio\": \"39e4af70-3df0-4a23-819e-e5c427ff02d3\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-panama\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Panama\",\n",
    "            \"isoCode\": \"PA\",\n",
    "            \"foretoldName\": \"@locations/n-panama\"\n",
    "        },\n",
    "        \"april19\": \"e1f5a738-16de-4579-8e93-3d97a952b168\",\n",
    "        \"april26\": \"460676be-f8b8-4c3e-bda7-344b9bc50a4e\",\n",
    "        \"may3\": \"7297b5d5-385b-4257-ac3e-857fea582cb9\",\n",
    "        \"may17\": \"546aa698-b11d-4192-8403-6981c48c3084\",\n",
    "        \"deathsAttributed\": \"f4d2cd4a-2530-4ba5-a6a5-f05125851657\",\n",
    "        \"infectionsAttributed\": \"3e16f071-b9b5-43a4-a67d-9fe0fa491880\",\n",
    "        \"timeToDeath\": \"b1d282bc-d827-4b82-a49d-3aa9e0bb2d77\",\n",
    "        \"infectionFatalityRatio\": \"8ae2f9b6-3260-4067-9c67-078061a4d04b\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-sao-paulo\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"São Paulo (Brazil)\",\n",
    "            \"foretoldName\": \"@locations/n-sao-paulo\"\n",
    "        },\n",
    "        \"april19\": \"21d1c054-f46a-4051-9150-d039872ac089\",\n",
    "        \"april26\": \"2d00c7ed-9fc3-4766-bd28-cafe950b02f4\",\n",
    "        \"may3\": \"c3b31fc8-043c-477f-b520-49d9f306ac8f\",\n",
    "        \"may17\": \"979b748f-c3a4-4f01-958c-98e1ce94dff5\",\n",
    "        \"deathsAttributed\": \"3fb64298-51df-4e15-ab83-10e18dcc4d7a\",\n",
    "        \"infectionsAttributed\": \"e61704de-064a-446b-8356-f6eec1b79326\",\n",
    "        \"timeToDeath\": \"7c067ce3-1677-492b-ba9f-f29af81c7f4e\",\n",
    "        \"infectionFatalityRatio\": \"95b74135-cf4d-4445-8581-76ee56c8e476\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-rio-de-janeiro\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Rio de Janeiro (Brazil)\",\n",
    "            \"foretoldName\": \"@locations/n-rio-de-janeiro\"\n",
    "        },\n",
    "        \"april19\": \"ef29c88e-5fdb-4e23-bc10-0e62d636dab8\",\n",
    "        \"april26\": \"5e299e50-4d29-44c9-ba46-bc0e71145c8a\",\n",
    "        \"may3\": \"0da9c2e3-866b-4655-9a02-6d1f99ed4210\",\n",
    "        \"may17\": \"2f414197-09f1-47ec-8719-5df3e0cb66d5\",\n",
    "        \"deathsAttributed\": \"96f105d7-c178-48fc-8a11-297d620df1bf\",\n",
    "        \"infectionsAttributed\": \"8c3e3c08-72f8-4367-8b80-e555e7cb775a\",\n",
    "        \"timeToDeath\": \"44a86f6b-bd9d-4ad6-8c55-4754813d6231\",\n",
    "        \"infectionFatalityRatio\": \"41f351c0-7413-411e-bdce-d94bb44fb791\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-belo-horizonte\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Belo Horizonte (Brazil)\",\n",
    "            \"foretoldName\": \"@locations/n-belo-horizonte\"\n",
    "        },\n",
    "        \"april19\": \"6883c7dc-0390-46a0-af99-9707aafee1c2\",\n",
    "        \"april26\": \"7778285b-84fa-4bf3-b560-44b6735c58fa\",\n",
    "        \"may3\": \"3098e88c-ee72-47a0-9cef-b398cd0e9243\",\n",
    "        \"may17\": \"79a13cfa-f751-4df2-b8d7-a0c5e1a36382\",\n",
    "        \"deathsAttributed\": \"a362f036-6535-4f7d-89e0-e9d7aeaf2d90\",\n",
    "        \"infectionsAttributed\": \"3968fdc8-ecae-49de-b93c-56c346d10db4\",\n",
    "        \"timeToDeath\": \"fb6224a6-9ccf-4e9e-92e3-843d9d4af4eb\",\n",
    "        \"infectionFatalityRatio\": \"cbadb95e-dd71-41c0-9061-a479334c2977\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-papua-new-guinea\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Papua New Guinea\",\n",
    "            \"isoCode\": \"PG\",\n",
    "            \"foretoldName\": \"@locations/n-papua-new-guinea\"\n",
    "        },\n",
    "        \"april19\": \"dde72ef6-4219-47a1-8714-e676af9bd8d1\",\n",
    "        \"april26\": \"1c9f44cd-ddb9-4400-8f5d-73081446739d\",\n",
    "        \"may3\": \"03838e80-64ef-493e-abcb-962d2527d17e\",\n",
    "        \"may17\": \"fc216a87-a28c-43ef-ad3e-9c6f705724ad\",\n",
    "        \"deathsAttributed\": \"a79095f8-9178-4ce6-bcdf-880057c728dd\",\n",
    "        \"infectionsAttributed\": \"288bca95-b216-4931-adf1-e6646293d103\",\n",
    "        \"timeToDeath\": \"c8f599d7-c681-43a4-82e8-742b46412d33\",\n",
    "        \"infectionFatalityRatio\": \"c85001d2-bd6f-4ecc-94ca-959077e7d92b\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"@locations/n-earth\",\n",
    "        \"locationData\": {\n",
    "            \"name\": \"Earth\",\n",
    "            \"isoCode\": \"W\",\n",
    "            \"foretoldName\": \"@locations/n-earth\"\n",
    "        },\n",
    "        \"may3\": \"e04ca67a-5b2c-4093-89f9-23921a70056e\",\n",
    "        \"deathsAttributed\": \"7a448d93-b3ea-4708-9a89-5e821c9d0aad\",\n",
    "        \"infectionsAttributed\": \"f39561c8-5d2b-448b-bef5-4557e64cca86\",\n",
    "        \"timeToDeath\": \"03fd9e12-01ba-46bf-8a6e-0230a7eab40a\",\n",
    "        \"infectionFatalityRatio\": \"fdc1580f-9cc8-4f2c-b3e7-9df81651e196\"\n",
    "    }\n",
    "]\n",
    "# Dummy data\n",
    "# foretold_lookup = [\n",
    "#     {\n",
    "#         \"name\": \"@locations/n-earth\",\n",
    "#         \"locationData\": {\n",
    "#             \"name\": \"Earth\",\n",
    "#             \"isoCode\": \"W\",\n",
    "#             \"foretoldName\": \"@locations/n-earth\"\n",
    "#         },\n",
    "#         \"may3\": \"e04ca67a-5b2c-4093-89f9-23921a70056e\",\n",
    "#         \"deathsAttributed\": \"77936da2-a581-48c7-add1-8a4ebc647c8c\",\n",
    "#         \"infectionsAttributed\": \"5f9eaaae-4d88-4fa4-9b8e-8bdc97613dc2\",\n",
    "#         \"timeToDeath\": \"399272c4-7b58-4a96-a68d-5a779ad4ffb3\",\n",
    "#         \"infectionFatalityRatio\": \"10ab95e3-f169-4caf-8865-6c8c3987851d\"\n",
    "#     },\n",
    "#     {\n",
    "#         \"name\": \"@locations/n-united-states-of-america\",\n",
    "#         \"locationData\": {\n",
    "#             \"name\": \"United States of America\",\n",
    "#             \"isoCode\": \"US \",\n",
    "#             \"foretoldName\": \"@locations/n-united-states-of-america\"\n",
    "#         },\n",
    "#         \"april19\": \"06deab80-6610-4bff-a75d-30a6028790dd\",\n",
    "#         \"april26\": \"38471260-a79a-4807-942d-0784aa19c2c2\",\n",
    "#         \"may3\": \"92c2f2f3-91aa-48b8-aaa3-c9bb402c0b08\",\n",
    "#         \"may17\": \"96040d3b-afcb-425a-a1ab-8fed5f5ea861\",\n",
    "#         # \"deathsAttributed\": \"e3d867f7-48b6-46b9-b4ff-30d03ce358b0\",\n",
    "#         # \"infectionsAttributed\": \"e3d867f7-48b6-46b9-b4ff-30d03ce358b0\",\n",
    "#         # \"timeToDeath\": \"4154fe1f-df9d-42d6-9f12-e03c21105611\",\n",
    "#         # \"infectionFatalityRatio\": \"e3d867f7-48b6-46b9-b4ff-30d03ce358b0\"\n",
    "#     },    \n",
    "# ]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load Foretold Parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "foretold = ergo.Foretold(foretold_token)\n",
    "foretold_distributions = {}\n",
    "for entry in tqdm.notebook.tqdm(foretold_lookup):\n",
    "  isoCode = entry[\"locationData\"].get(\"isoCode\", None)\n",
    "  if isoCode is not None:\n",
    "    isoCode = isoCode.strip()\n",
    "    d = {}\n",
    "    for key, value in entry.items():\n",
    "      if key not in [\"name\", \"locationData\"]:\n",
    "        try:\n",
    "          d[key] = foretold.get_question(value)\n",
    "        except TypeError:\n",
    "          pass\n",
    "    foretold_distributions[isoCode] = d"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cases Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rds = epimodel.RegionDataset.load('epimodel/data/regions.csv')\n",
    "cases_raw = epimodel.read_csv('epimodel/data/johns-hopkins.csv', rds)\n",
    "\n",
    "# List of region codes to run predictions for\n",
    "codes_to_predict = [x for x in cases_raw.index.get_level_values(0).unique().values if isinstance(x, str)]\n",
    "last_available_date = cases_raw.index.get_level_values(1).unique().values[-1]\n",
    "print(\"Most recent available data is from \" + str(last_available_date)[:10])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "predict_date = last_available_date\n",
    "\n",
    "# Can set if you want to predict infections at a past date\n",
    "cutoff_date = None # datetime.date(2020,4,2)\n",
    "if cutoff_date is not None:\n",
    "  cases_raw = cases_raw[[(ix[1]<= cutoff_date) for ix in cases_raw.index]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Restrict to countries with > 1000 cases and > 10 deaths"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cases_with_enough_data = (cases_raw\n",
    "         .groupby(\"Code\").filter(lambda x: x[\"Confirmed\"].max() > 1000)\n",
    "         .groupby(\"Code\").filter(lambda x: x[\"Deaths\"].max() > 10))\n",
    "\n",
    "codes_to_predict = [x for x in cases_with_enough_data.index.get_level_values(0).unique().values if isinstance(x, str)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data Retrieval Functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define functions to lookup data and parameters\n",
    "# If you need to override parametes, you can add if statements to override the\n",
    "# values for a particular region\n",
    "\n",
    "# Pandas lookup is pretty slow, so we just convert to dictionaries + numpy array\n",
    "cases = {}\n",
    "for code in codes_to_predict:\n",
    "  cases[code] = {\n",
    "      'Deaths': cases_raw.loc[code]['Deaths'].values,\n",
    "       'Recovered': cases_raw.loc[code]['Recovered'].values,\n",
    "       'Confirmed': cases_raw.loc[code]['Confirmed'].values,\n",
    "  }\n",
    "  \n",
    "def latest_deaths(code):\n",
    "    return cases[code]['Deaths'][-1]\n",
    "\n",
    "def latest_recovered(code):\n",
    "  return cases[code]['Recovered'][-1]\n",
    "\n",
    "def confirmed_n_days_ago(code, n):\n",
    "  return cases[code]['Confirmed'][-1 -n]\n",
    "\n",
    "def get_parameter(code, name):\n",
    "  try:\n",
    "    return float(parameters[code][\"DeathMultiplier\"])\n",
    "  except (KeyError, ValueError):\n",
    "    return np.NaN\n",
    "\n",
    "\n",
    "def death_multiplier(code):\n",
    "  \"\"\"How many more deaths have occurred than were reported\"\"\"\n",
    "  if code in foretold_distributions:\n",
    "    if \"deathsAttributed\" in foretold_distributions[code]:\n",
    "      return 1 / foretold_distributions[code][\"deathsAttributed\"].sample_community()\n",
    "  v = get_parameter(code,\"DeathMultiplier\")\n",
    "  if not np.isnan(v):\n",
    "    return v\n",
    "  return 1 / foretold_distributions[\"W\"][\"deathsAttributed\"].sample_community()\n",
    "\n",
    "def ascertainment_parameter(code):\n",
    "  \"\"\"How many more infections have occurred than were reported\"\"\"\n",
    "  if code in foretold_distributions:\n",
    "    if \"infectionsAttributed\" in foretold_distributions[code]:\n",
    "      return 1 / foretold_distributions[code][\"infectionsAttributed\"].sample_community()\n",
    "  v = get_parameter(code,\"AscertainmentParameter\")\n",
    "  if not np.isnan(v):\n",
    "    return v      \n",
    "  return 1 / foretold_distributions[\"W\"][\"infectionsAttributed\"].sample_community()  \n",
    "\n",
    "def days_to_death(code):\n",
    "  \"\"\"How many days between someone being infected and dying\"\"\"\n",
    "  if code in foretold_distributions:\n",
    "    if \"timeToDeath\" in foretold_distributions[code]:\n",
    "      return foretold_distributions[code][\"timeToDeath\"].sample_community()\n",
    "  v = get_parameter(code,\"timeToDeath\")\n",
    "  if not np.isnan(v):\n",
    "    return v      \n",
    "  return foretold_distributions[\"W\"][\"timeToDeath\"].sample_community()\n",
    "\n",
    "def date_offset(d1, d2):\n",
    "  \"\"\"What is the difference in days between these two dates\"\"\"\n",
    "  return (d1- d2)/np.timedelta64(1, 'D')\n",
    "\n",
    "def sample_foretold(code, predict_date, max_extrapolation_days=3):\n",
    "  \"\"\"\n",
    "  Sample predictions from foretold for predict_date.\n",
    "  If we're in the range of dates with available predictions, interpolate in log\n",
    "  space between the nearest predictions. \n",
    "  If we're outside but within max_extrapolation_days of the first/last \n",
    "  prediction, return the first/last prediction (without extrapolating yet). \n",
    "  If we're outside the range, return np.NaN. \n",
    "  If one of the predictions needed for interpolation is missing, return\n",
    "  np.NaN\n",
    "  \"\"\"\n",
    "  assert isinstance(predict_date, np.datetime64)\n",
    "\n",
    "  if code not in foretold_distributions:\n",
    "    return np.NaN\n",
    "  dists = foretold_distributions[code]\n",
    "\n",
    "  prediction_dates = np.array(['2020-04-19','2020-04-26','2020-05-03','2020-05-17']).astype(np.datetime64)\n",
    "  prediction_names = [\"april19\", \"april26\", \"may3\", \"may17\"]\n",
    "\n",
    "  x = date_offset(predict_date, prediction_dates[0])\n",
    "\n",
    "  # Sample the same quantile for each distribution\n",
    "  q = ergo.uniform()\n",
    "  xs = [date_offset(d, prediction_dates[0]) for d in prediction_dates]\n",
    "\n",
    "  # If we're too far outside of the range where we have predictions, return NaN\n",
    "  if x < -max_extrapolation_days or x > xs[-1] + max_extrapolation_days:\n",
    "    return np.NaN\n",
    "\n",
    "  ys = np.array([\n",
    "                   dists[n].quantile(q) if n in dists else np.NaN\n",
    "                   for n in prediction_names\n",
    "                   ])\n",
    "\n",
    "  # Interpolate in log space\n",
    "  return np.exp(np.interp(x, xs, np.log(ys)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Model\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def model(codes_to_predict):\n",
    "  growth_window_days = 17 # When estimating growth rate, look at this length of past growth\n",
    "  canonical_mortality_rate = foretold_distributions[\"W\"][\"infectionFatalityRatio\"].sample_community()\n",
    "  max_mortality_rate = 0.05\n",
    "  max_growth_multiplier = 64\n",
    "  recovery_time = 17 # TODO: improve estimate\n",
    "\n",
    "  def mortality_rate(code):\n",
    "    \"\"\"Most recent fraction of deaths out of resolved cases (death and confirmed)\"\"\"\n",
    "    if code in foretold_distributions:\n",
    "      if \"infectionFatalityRatio\" in foretold_distributions[code]:\n",
    "        return foretold_distributions[code][\"infectionFatalityRatio\"].sample_community()\n",
    "    v = get_parameter(code,\"infectionFatalityRatio\")\n",
    "    if not np.isnan(v):\n",
    "      return v              \n",
    "    return min(latest_deaths(code) / latest_deaths(code) + latest_recovered(code), max_mortality_rate)\n",
    "\n",
    "  def growth_rate(code):\n",
    "    \"\"\"How much does the number of cases grow every day?\"\"\"\n",
    "    # This might give bad estimates for the growth rate if a country had few cases at days_to_death days ago.\n",
    "    # We could make this estimate better if we look for the first date that a country crosses some # of cases threshold (e.g. 100 cases)    \n",
    "    growth_multiplier = min(confirmed_n_days_ago(code, 0) / confirmed_n_days_ago(code, growth_window_days), max_growth_multiplier)\n",
    "    return growth_multiplier ** (1/growth_window_days)\n",
    "\n",
    "  for code in codes_to_predict:\n",
    "    active_estimates = []\n",
    "\n",
    "    def add_estimate(value, n):\n",
    "      if not isinstance(value, torch.Tensor):\n",
    "        value = torch.tensor(value)\n",
    "      if not torch.isnan(value):\n",
    "        active_estimates.append(value)\n",
    "        ergo.tag(value, f\"{code} active_estimate_{n}\")\n",
    "\n",
    "    # Model 1 - country specific mortality rate\n",
    "    deaths_estimate = death_multiplier(code) * latest_deaths(code) \n",
    "    cumulative_infections = deaths_estimate * (growth_rate(code) ** days_to_death(code)) * (1 / mortality_rate(code))\n",
    "    recovered_infections = cumulative_infections / (growth_rate(code) ** (recovery_time))\n",
    "    active_estimate_1 = cumulative_infections - recovered_infections\n",
    "    add_estimate(active_estimate_1, 1)\n",
    "\n",
    "    # Model 2 - global mortality rate\n",
    "    deaths_estimate = death_multiplier(code) * latest_deaths(code) \n",
    "    cumulative_infections = deaths_estimate * (growth_rate(code) ** days_to_death(code)) * (1 / canonical_mortality_rate)\n",
    "    recovered_infections = cumulative_infections / (growth_rate(code) ** (recovery_time))\n",
    "    active_estimate_2 = cumulative_infections - recovered_infections\n",
    "    add_estimate(active_estimate_2, 2)\n",
    "\n",
    "    # Model 3 - fraction of cases ascertained\n",
    "    recovered_estimate = confirmed_n_days_ago(code, 0) / (growth_rate(code) ** days_to_death(code))\n",
    "    active_estimate_3 = (confirmed_n_days_ago(code, 0) - recovered_estimate) * ascertainment_parameter(code)\n",
    "    add_estimate(active_estimate_3, 3)\n",
    "\n",
    "    # Model 4 - foretold prediction    \n",
    "    active_estimate_4 =  sample_foretold(code, predict_date)\n",
    "    add_estimate(active_estimate_4, 4)\n",
    "      \n",
    "    if active_estimates:\n",
    "      active_estimate_combined = ergo.random_choice(active_estimates)\n",
    "      ergo.tag(active_estimate_combined, f\"{code} active_estimate_combined\")    \n",
    "  \n",
    "# Get samples from model for all variables\n",
    "samples = ergo.run(lambda: model(codes_to_predict), num_samples=200)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "samples.describe().transpose().round(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Output File"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Make the output dataframe\n",
    "def make_quantiles_df(codes_to_predict, samples):\n",
    "  quantiles =[0.05 * i for i in range(21)]\n",
    "  data = []\n",
    "  codes = []\n",
    "  for code in codes_to_predict:\n",
    "    name = f\"{code} active_estimate_combined\"\n",
    "    if name in samples:\n",
    "      series = samples[name]\n",
    "      codes.append(code)\n",
    "      data.append({\n",
    "          \"Name\":regions[code].get_display_name(),\n",
    "          \"Date\":str(predict_date).split(\"T\")[0],\n",
    "          **{\n",
    "          str(round(q,2)): series.quantile(q) for q in quantiles \n",
    "          }})\n",
    "  df = pd.DataFrame(data, index=codes)\n",
    "  df.index.name = \"Code\"\n",
    "  return df\n",
    "\n",
    "quantiles_df = make_quantiles_df(codes_to_predict, samples).round(0)\n",
    "display(quantiles_df)\n",
    "quantiles_df.to_csv(\"active_infections_prediction.csv\")\n",
    "# If this doesn't work, you can find this file in the files pane at the side of\n",
    "# the screen, right click and download\n",
    "time.sleep(5) # I think it's failing sometimes because the file isn't available yet?\n",
    "try:\n",
    "  google.colab.files.download(\"active_infections_prediction.csv\")\n",
    "except:\n",
    "  pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Can plot selected distributions for debugging\n",
    "for code in [\"US\", \"AE\"]:\n",
    "  try:\n",
    "    s = samples[f\"{code} active_estimate_combined\"]\n",
    "    seaborn.distplot(s)\n",
    "    plt.show()\n",
    "  except KeyError:\n",
    "    pass"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Countermeasures\n",
    "\n",
    "This part of the notebook allows you to do scenario modelling using probability distributions, and then automatically turn those scenarios into GLEAMviz definition files [1].\n",
    "\n",
    "### Basic usage\n",
    "\n",
    "Scenarios are specified in spreadsheets; where each free parameter can either be specified as a number or as the ID of a Foretold distribution.\n",
    "\n",
    "[This document](https://docs.google.com/document/d/1CJmoL0ypDTKjtpVLdyVTajeqKRp4HKujEduavkwobl8/edit?usp=sharing) explains how to format the spreadsheet, and [here](https://docs.google.com/spreadsheets/d/1kAboAHnu2KK8p-1adM8L4ngrMfr2EmOsVICwfFKCEPE/edit?usp=sharing) is an example spreadsheet. Any Foretold distribution should be added to [this channel](https://www.foretold.io/c/93c557b5-ac8d-4201-a6d7-7ca2d2574304).\n",
    "\n",
    "Then use the function: `make_countermeasures_csv(countermeasures_url, countermeasures_sheet)`\n",
    "\n",
    "\n",
    "---\n",
    "\n",
    "[1] Note: at the moment this outputs a CSV version of the spreadsheet, [this issue](https://github.com/epidemics/covid/issues/406) tracks when it will be able to automatically generate gleam files.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Make countermeasures CSV\n",
    "def make_countermeasures_csv(countermeasures_url, countermeasures_sheet):\n",
    "  input_data = load_spreadsheet(countermeasures_url, countermeasures_sheet)\n",
    "  headers = input_data[0]\n",
    "  value_column = headers.index(\"Value\")\n",
    "  output_data = []\n",
    "  num_samples = 100\n",
    "\n",
    "  quantiles =[0.05 * i for i in range(21)]\n",
    "\n",
    "  for row in tqdm.notebook.tqdm(input_data[1:]):\n",
    "    d = {h: v for (h,v) in zip(headers, row)}\n",
    "    value = row[value_column]\n",
    "    if is_uuid(value):\n",
    "      foretold_question = foretold.get_question(value)\n",
    "      d.update({\n",
    "          str(round(q,2)): foretold_question.quantile(q) for q in quantiles \n",
    "          })\n",
    "    else:\n",
    "      d.update({\n",
    "          str(round(q,2)): value for q in quantiles \n",
    "          })\n",
    "    output_data.append(d)\n",
    "  countermeasures_df = pd.DataFrame(output_data)\n",
    "  display(countermeasures_df)\n",
    "\n",
    "  countermeasures_df.to_csv(\"countermeasures.csv\")\n",
    "  # If this doesn't work, you can find this file in the files pane at the side of\n",
    "  # the screen, right click and download\n",
    "  time.sleep(1)\n",
    "  try:\n",
    "    google.colab.files.download(\"countermeasures.csv\")\n",
    "  except:\n",
    "    pass\n",
    "\n",
    "make_countermeasures_csv(\"https://docs.google.com/spreadsheets/d/1kAboAHnu2KK8p-1adM8L4ngrMfr2EmOsVICwfFKCEPE/edit#gid=0\",\n",
    "                         \"Sheet1\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Generate gleam files\n",
    "\n",
    "In `epimodel.gleam.definition`, there is a class `GleamDefinition` with many methods for manipulating a given definition XML - add seed regions, add exceptions, adjust parameters.\n",
    "\n",
    "For example of usage, see `generate_simulations`. It generates an entire batch for the website, but the main steps are the same.\n",
    "\n",
    "One of the steps is to take region estimates (e.g. countries or states) and distribute these down to Gleam \"basins\" (city-like regions). This is done by our function `algorithms.distribute_down_with_population` in the above.\n",
    "The modelers need a starting XML - I would let them provide it if they want to modify the disease params etc."
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all",
   "main_language": "python",
   "notebook_metadata_filter": "-all"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
